﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace eBook.Core
{
  public class ISBN10 : ISBN
  {       
	  private Regex _isbn10exp = new Regex(@"^\d{9}[0-9X]$");

    #region Constructors 
    
    public ISBN10( string isbnval ) : base( isbnval )
    {

    } 
    
    #endregion

    #region Overrides 
    
    // converts the 10-digit ISBN to a 13-digit ISBN
    public override string Transform()
    {
      if ( !this.Validate() )
        return _isbnval;

      // omit isbn10 check-digit, add prefix, find isbn13 check-digit
      string partISBN = "978" + _strippedISBN.Substring( 0, 9 );
      int total = 0;
      int y = 0;
      for ( int x = 0; x < 12; x++ )
      {
        y = x % 2 == 0 ? 1 : 3;
        total += y * CharToDigitValue( partISBN[x] );
      }
      int z = ( 10 - ( total % 10 ) ) % 10;

      return partISBN + z.ToString();
    }

    public override bool Validate()
    {
      if ( this.ValidationError != ISBNValidationError.NotYetValidated )
        return this.ValidationError == ISBNValidationError.None;

      if ( _strippedISBN.Length != 10 )
      {
        this.ValidationError = ISBNValidationError.InvalidInputSize;
        return false;
      }

      if ( !( _isbn10exp.IsMatch( _strippedISBN ) ) )
      {
        this.ValidationError = ISBNValidationError.InvalidCharacters;
        return false;
      }

      #region Validation logic 
      
      int total = 0;
      // Formulated number must be divisible by 11
      for ( var x = 0; x < 9; x++ )
        total += CharToDigitValue( _strippedISBN[x] ) * ( 10 - x );

      char checkDigit = _strippedISBN[9];
      int z = checkDigit == 'X' ? 10 : CharToDigitValue( checkDigit );

      bool result = ( total + z ) % 11 == 0; 
      
      #endregion
      
      if ( result )
        this.ValidationError = ISBNValidationError.None;
      else
        this.ValidationError = ISBNValidationError.CheckDigitError;

      return result;
    }

    public override string Hyphenate()
    {
      if ( !this.Validate() )
        return string.Format( "ERROR ({0})", this.ValidationError );

      return new ISBNHyphenator().HyphenateISBN10( _strippedISBN );
    } 
    
    #endregion
        
  }
  
  
}
